allow FormConfigurable text areas to be syntax highlighted; allow JavaScriptAgent to be dry run

Andrew Cantino 10 lat temu
rodzic
commit
d3564c18fd

+ 3 - 0
app/assets/javascripts/ace.js.coffee

@@ -0,0 +1,3 @@
1
+#= require ace/ace
2
+#= require ace/mode-javascript.js
3
+#= require ace/mode-markdown.js

+ 30 - 2
app/assets/javascripts/pages/agent-edit-page.js.coffee

@@ -2,6 +2,7 @@ class @AgentEditPage
2 2
   constructor: ->
3 3
     $("#agent_source_ids").on "change", @showEventDescriptions
4 4
     @showCorrectRegionsOnStartup()
5
+    $("form.agent-form").on "submit", => @updateFromEditors()
5 6
 
6 7
     # The type selector is only available on the new agent form.
7 8
     if $("#agent_type").length
@@ -9,6 +10,7 @@ class @AgentEditPage
9 10
       @handleTypeChange(true)
10 11
     else
11 12
       @enableDryRunButton()
13
+      @buildAce()
12 14
 
13 15
   handleTypeChange: (firstTime) ->
14 16
     $(".event-descriptions").html("").hide()
@@ -53,6 +55,7 @@ class @AgentEditPage
53 55
           window.jsonEditor = setupJsonEditor()[0]
54 56
 
55 57
         @enableDryRunButton()
58
+        @buildAce()
56 59
 
57 60
         window.initializeFormCompletable()
58 61
 
@@ -126,17 +129,42 @@ class @AgentEditPage
126 129
       else
127 130
         @hideEventCreation()
128 131
 
132
+  buildAce: ->
133
+    $(".ace-editor").each ->
134
+      unless $(this).data('initialized')
135
+        $(this).data('initialized', true)
136
+        $source = $($(this).data('source')).hide()
137
+        syntax = $(this).data('syntax')
138
+        editor = ace.edit(this)
139
+        $(this).data('ace-editor', editor)
140
+        editor.getSession().setTabSize(2)
141
+        editor.getSession().setUseSoftTabs(true)
142
+        editor.getSession().setUseWrapMode(false)
143
+        editor.setTheme("ace/theme/chrome")
144
+        if syntax == 'javascript'
145
+          editor.getSession().setMode("ace/mode/javascript")
146
+        else
147
+          editor.getSession().setMode("ace/mode/text")
148
+
149
+        editor.getSession().setValue($source.val())
150
+
151
+  updateFromEditors: ->
152
+    $(".ace-editor").each ->
153
+      $source = $($(this).data('source'))
154
+      $source.val($(this).data('ace-editor').getSession().getValue())
155
+
129 156
   enableDryRunButton: ->
130 157
     $(".agent-dry-run-button").prop('disabled', false).off().on "click", @invokeDryRun
131 158
 
132 159
   disableDryRunButton: ->
133 160
     $(".agent-dry-run-button").prop('disabled', true)
134 161
 
135
-  invokeDryRun: (e) ->
162
+  invokeDryRun: (e) =>
136 163
     e.preventDefault()
137
-    button = this
164
+    button = e.target
138 165
     $(button).prop('disabled', true)
139 166
     $('body').css(cursor: 'progress')
167
+    @updateFromEditors()
140 168
     $.ajax type: 'POST', url: $(button).data('action-url'), dataType: 'json', data: $(button.form).serialize()
141 169
       .always =>
142 170
         $("body").css(cursor: 'auto')

+ 26 - 0
app/assets/javascripts/pages/user-credential-page.js.coffee

@@ -0,0 +1,26 @@
1
+class @UserCredentialPage
2
+  constructor: ->
3
+    editor = ace.edit("ace-credential-value")
4
+    editor.getSession().setTabSize(2)
5
+    editor.getSession().setUseSoftTabs(true)
6
+    editor.getSession().setUseWrapMode(false)
7
+    editor.setTheme("ace/theme/chrome")
8
+
9
+    setMode = ->
10
+      mode = $("#user_credential_mode").val()
11
+      if mode == 'java_script'
12
+        editor.getSession().setMode("ace/mode/javascript")
13
+      else
14
+        editor.getSession().setMode("ace/mode/text")
15
+
16
+    setMode()
17
+    $("#user_credential_mode").on 'change', setMode
18
+
19
+    $textarea = $('#user_credential_credential_value').hide()
20
+    editor.getSession().setValue($textarea.val())
21
+
22
+    $textarea.closest('form').on 'submit', ->
23
+      $textarea.val(editor.getSession().getValue())
24
+
25
+$ ->
26
+  Utils.registerPage(UserCredentialPage, forPathsMatching: /^user_credentials\/\d+/)

+ 0 - 29
app/assets/javascripts/user_credentials.js.coffee

@@ -1,29 +0,0 @@
1
-#= require ace/ace
2
-#= require ace/mode-javascript.js
3
-#= require ace/mode-markdown.js
4
-#= require_self
5
-
6
-# This is not included in the core application.js bundle.
7
-
8
-$ ->
9
-  editor = ace.edit("ace-credential-value")
10
-  editor.getSession().setTabSize(2)
11
-  editor.getSession().setUseSoftTabs(true)
12
-  editor.getSession().setUseWrapMode(false)
13
-  editor.setTheme("ace/theme/chrome")
14
-
15
-  setMode = ->
16
-    mode = $("#user_credential_mode").val()
17
-    if mode == 'java_script'
18
-      editor.getSession().setMode("ace/mode/javascript")
19
-    else
20
-      editor.getSession().setMode("ace/mode/text")
21
-
22
-  setMode()
23
-  $("#user_credential_mode").on 'change', setMode
24
-
25
-  $textarea = $('#user_credential_credential_value').hide()
26
-  editor.getSession().setValue($textarea.val())
27
-
28
-  $textarea.closest('form').on 'submit', ->
29
-    $textarea.val(editor.getSession().getValue())

+ 3 - 3
app/assets/stylesheets/application.css.scss.erb

@@ -172,12 +172,12 @@ span.not-applicable:after {
172 172
   font-weight: bold;
173 173
 }
174 174
 
175
-// Credentials
175
+// Credentials and Ace Editor
176 176
 
177
-#ace-credential-value {
177
+#ace-credential-value, .ace-editor {
178 178
   position: relative;
179 179
   width: 940px;
180
-  height: 400px;
180
+  height: 300px;
181 181
 }
182 182
 
183 183
 // Disabled

+ 1 - 1
app/concerns/form_configurable.rb

@@ -32,7 +32,7 @@ module FormConfigurable
32 32
       options = args.extract_options!.reverse_merge(roles: [], type: :string)
33 33
 
34 34
       if args.all? { |arg| arg.is_a?(Symbol) }
35
-        options.assert_valid_keys([:type, :roles, :values])
35
+        options.assert_valid_keys([:type, :roles, :values, :syntax])
36 36
       end
37 37
 
38 38
       if options[:type] == :array && (options[:values].blank? || !options[:values].is_a?(Array))

+ 6 - 0
app/helpers/application_helper.rb

@@ -84,6 +84,12 @@ module ApplicationHelper
84 84
     ].join.html_safe, class: "label label-default label-service service-#{service.provider}"
85 85
   end
86 86
 
87
+  def load_ace_editor!
88
+    unless content_for?(:ace_editor_script)
89
+      content_for :ace_editor_script, javascript_include_tag('ace')
90
+    end
91
+  end
92
+
87 93
   def highlighted?(id)
88 94
     @highlighted_ranges ||=
89 95
       case value = params[:hl].presence

+ 10 - 2
app/models/agents/java_script_agent.rb

@@ -3,6 +3,10 @@ require 'cgi'
3 3
 
4 4
 module Agents
5 5
   class JavaScriptAgent < Agent
6
+    include FormConfigurable
7
+
8
+    can_dry_run!
9
+
6 10
     default_schedule "never"
7 11
 
8 12
     description <<-MD
@@ -23,6 +27,10 @@ module Agents
23 27
       * `this.error(message)`
24 28
     MD
25 29
 
30
+    form_configurable :code, type: :text, syntax: :javascript
31
+    form_configurable :expected_receive_period_in_days
32
+    form_configurable :expected_update_period_in_days
33
+
26 34
     def validate_options
27 35
       cred_name = credential_referenced_by_code
28 36
       if cred_name
@@ -67,7 +75,7 @@ module Agents
67 75
             this.memory('callCount', callCount + 1);
68 76
           }
69 77
         };
70
-        
78
+
71 79
         Agent.receive = function() {
72 80
           var events = this.incomingEvents();
73 81
           for(var i = 0; i < events.length; i++) {
@@ -77,7 +85,7 @@ module Agents
77 85
       JS
78 86
 
79 87
       {
80
-        "code" => js_code.gsub(/[\n\r\t]/, '').strip,
88
+        "code" => Utils.unindent(js_code),
81 89
         'expected_receive_period_in_days' => "2",
82 90
         'expected_update_period_in_days' => "2"
83 91
       }

+ 1 - 1
app/models/agents/website_agent.rb

@@ -376,7 +376,7 @@ module Agents
376 376
       end
377 377
     end
378 378
 
379
-    # Wraps Faraday::Utilsa::Headers
379
+    # Wraps Faraday::Utils::Headers
380 380
     class HeaderDrop < LiquidDroppable::Drop
381 381
       def before_method(name)
382 382
         @object[name.tr('_', '-')]

+ 6 - 1
app/presenters/form_configurable_agent_presenter.rb

@@ -20,7 +20,12 @@ class FormConfigurableAgentPresenter < Decorator
20 20
 
21 21
     case data[:type]
22 22
     when :text
23
-      @view.text_area_tag "agent[options][#{attribute}]", value, html_options.merge(class: 'form-control', rows: 3)
23
+      @view.content_tag 'div' do
24
+        @view.concat @view.text_area_tag("agent[options][#{attribute}]", value, html_options.merge(class: 'form-control', rows: 3))
25
+        if data[:syntax].present?
26
+          @view.concat @view.content_tag('div', '', class: 'ace-editor', data: { source: "[name='agent[options][#{attribute}]']", syntax: data[:syntax] })
27
+        end
28
+      end
24 29
     when :boolean
25 30
       @view.content_tag 'div' do
26 31
         @view.concat(@view.content_tag('label', class: 'radio-inline') do

+ 6 - 3
app/views/agents/_form.html.erb

@@ -1,3 +1,5 @@
1
+<% load_ace_editor! %>
2
+
1 3
 <% if @agent.errors.any? %>
2 4
   <div class="row well model-errors">
3 5
     <h2><%= pluralize(@agent.errors.count, "error") %> prohibited this Agent from being saved:</h2>
@@ -8,9 +10,10 @@
8 10
 <% end %>
9 11
 
10 12
 <%= form_for(@agent,
11
-             :as => :agent,
12
-             :url => @agent.new_record? ? agents_path : agent_path(@agent),
13
-             :method => @agent.new_record? ? "POST" : "PUT") do |f| %>
13
+             as: :agent,
14
+             url: @agent.new_record? ? agents_path : agent_path(@agent),
15
+             method: @agent.new_record? ? "POST" : "PUT",
16
+             html: { class: 'agent-form' }) do |f| %>
14 17
 
15 18
   <div class="row">
16 19
     <div class="col-md-6">

+ 1 - 0
app/views/layouts/application.html.erb

@@ -9,6 +9,7 @@
9 9
     <%= stylesheet_link_tag    "application", :media => "all" %>
10 10
     <%= javascript_include_tag "application" %>
11 11
     <%= csrf_meta_tags %>
12
+    <%= yield(:ace_editor_script) %>
12 13
     <%= yield(:head) %>
13 14
   </head>
14 15
   <body>

+ 2 - 2
app/views/user_credentials/_form.html.erb

@@ -1,3 +1,5 @@
1
+<% load_ace_editor! %>
2
+
1 3
 <%= form_for(@user_credential, :method => @user_credential.new_record? ? "POST" : "PUT") do |f| %>
2 4
   <% if @user_credential.errors.any? %>
3 5
     <div class="row well">
@@ -40,5 +42,3 @@
40 42
     </div>
41 43
   </div>
42 44
 <% end %>
43
-
44
-<%= javascript_include_tag "user_credentials" %>

+ 1 - 1
config/environments/production.rb

@@ -63,7 +63,7 @@ Huginn::Application.configure do
63 63
   end
64 64
 
65 65
   # Precompile additional assets (application.js.coffee.erb, application.css, and all non-JS/CSS are already added)
66
-  config.assets.precompile += %w( diagram.js graphing.js map_marker.js user_credentials.js )
66
+  config.assets.precompile += %w( diagram.js graphing.js map_marker.js ace.js )
67 67
 
68 68
   # Ignore bad email addresses and do not raise email delivery errors.
69 69
   # Set this to true and configure the email server for immediate delivery to raise delivery errors.